
import pygtk
pygtk.require('2.0')
import gtk
import _emulator

import pango

#text style flags
STYLE_BOLD           = 0x01 #enables bold text.
STYLE_UNDERLINE      = 0x02 #enables underlined text.
STYLE_ITALIC         = 0x04 #enables italicized text.
STYLE_STRIKETHROUGH  = 0x08 #enables marking text with strikethrough formatting.

#text highlight flags
HIGHLIGHT_STANDARD   = 0x10 #enables standard highlight.
HIGHLIGHT_ROUNDED    = 0x20 #enables rounded highlight.
HIGHLIGHT_SHADOW     = 0x40 #enables shadow highlight.

_HIGHLIGHT_ANY = HIGHLIGHT_STANDARD | HIGHLIGHT_ROUNDED | HIGHLIGHT_SHADOW

__colorconv = 65535 / 255

def _toGDKColor(color):
    if isinstance(color, tuple):
	r = color[0] * __colorconv
        g = color[1] * __colorconv
        b = color[2] * __colorconv
    else:
	r = ((color & 0xFF0000) >> 16) * __colorconv
        g = ((color & 0x00FF00) >> 8) * __colorconv
        b = (color & 0x0000FF) * __colorconv

    return gtk.gdk.Color(r, g, b)


class Text(object):
    """Text is a text editor UI control."""

    def _get_color(self):
        return self.__color
    def _set_color(self, value):
        self._color = value
        self._tagChanged = True
    color = property(fget=_get_color, fset=_set_color, doc="color attribute")

    #not sure about this attribute
    def _get_focus(self):
        return self._focus
    def _set_focus(self, value):
        self._focus = value
    focus = property(fget=_get_focus, fset=_set_focus, doc="focus attribute")

    def _get_font(self):
        return self._font
    def _set_font(self, value):
        if value in self._named_fonts:
            value = self._named_fonts[value]
        self._font = value
        self._tagChanged = True
    font = property(fget=_get_font, fset=_set_font, doc="font attribute")

    #this attribute not implemented
    def _get_highlight_color(self):
        return self._highlight_color
    def _set_highlight_color(self, value):
        self._highlight_color = value
        self._tagChanged = True
    highlight_color = property(fget=_get_highlight_color, fset=_set_highlight_color, doc="highlight_color attribute")

    def _get_style(self):
        return self._style
    def _set_style(self, value):
        self._style = value
        self._tagChanged = True
    style = property(fget=_get_style, fset=_set_style, doc="style attribute")
                            
                            
    def __init__(self):
        self._color = (0,0,0)
        self._focus = True
        self._font = u"Latin 12"
        self._highlight_color = (65534,65534,65534)
        self._style = 0
	self._bindings = {}

        self._named_fonts = {
            u"annotation":u"Latin 12",
            u"title":u"Latin 14",
            u"legend":u"Latin 10",
            u"symbol":u"Latin 12",
            u"dense":u"Latin 8",
            u"normal":u"Latin 12",
            }
        
	
	self._view = gtk.TextView()
        self._buffer = self._view.get_buffer()
        self._view.set_editable(True)
        self._view.set_cursor_visible(True)
        self._view.set_wrap_mode(gtk.WRAP_WORD)

        self._view.connect('focus_in_event', lambda w, e, d = None : self._OnFocus(True))
        self._view.connect('focus_out_event', lambda w, e, d = None : self._OnFocus(False))
        self._view.connect('key_press_event', self._OnKeyPress)

        self._tag = None
        self._tags = []
        self._tagChanged = True

        self._view.show()

        self._ctrl = self._view


    def add(self, text):
        """Inserts the Unicode string text to the current cursor position."""
        self._makeTag()
        insertmark = self._buffer.get_insert()
        iter = self._buffer.get_iter_at_mark(insertmark)
        self._buffer.insert_with_tags(iter, text, self._tag)

    def bind(self, event_code, callback):
        """Binds the callable Python object callback to event event_code. 
        
        The key codes are defined
        in the key_codes library module. The call bind(event_code, None) clears an existing
        binding. In the current implementation the event is always passed also to the underlying native
        UI control.
        """
        code = event_code #key_mappings.get(key)
        if code is not None:
            self._bindings[code] = callback
    
    def clear(self):
        """Clears the editor."""
        self._removeAllTags()
        start = self._buffer.get_start_iter()
        end = self._buffer.get_end_iter()
        self._buffer.delete(start, end)
    
    def delete(self, pos = 0, len = None):
        """Deletes len characters of the text held by the editor control, starting from the position pos."""
        # Problem is possible here - when text is deleted,
        # unused tags are not removed from the tagtable and list
        start = self._buffer.get_iter_at_offset(pos)
        
        if len is not None:
            end = self._buffer.get_iter_at_offset(pos + len)
        else:
            end = self._buffer.get_end_iter()
            
        self._buffer.delete(start, end)
    
    def get_pos(self):
        """Returns the current cursor position."""
        insertmark = self._buffer.get_insert()
        iter = self._buffer.get_iter_at_mark(insertmark)
        return iter.get_offset()
    
    def len(self):
        """Returns the length of the text string held by the editor control."""
        return  self._buffer.get_char_count()
    
    def get(self, pos = 0, len = None):
        """Retrieves len characters of the text held by the editor control, starting from the position pos."""
        start = self._buffer.get_iter_at_offset(pos)

        if len is not None:
            end = self._buffer.get_iter_at_offset(pos + len)
        else:
            end = self._buffer.get_end_iter()

        return self._buffer.get_text(start, end)
    
    def set(self, text):
        """Sets the text content of the editor control to Unicode string text."""
        self._removeAllTags()
        self._makeTag()
        self._buffer.set_text(text)
        self._buffer.apply_tag(
            self._tag,
            self._buffer.get_start_iter(),
            self._buffer.get_end_iter())
    
    def set_pos(self, cursor_pos):
        """Sets the cursor to cursor_pos."""
        iter = self._buffer.get_iter_at_offset(sursor_pos)
        self._buffer.place_cursor(iter)

    def _removeAllTags(self):
        table = self._buffer.get_tag_table()
        for tag in self._tags:
            table.remove(tag)
        self._tags = []
        self._tagChanged = True
        
    def _makeTag(self):
        if self._tagChanged:
            self._tag = self._buffer.create_tag()
   
            self._tag.set_property('foreground_gdk', _toGDKColor(self._color))
            if self._style & _HIGHLIGHT_ANY:
                self._tag.set_property('background_gdk', _toGDKColor(self._highlight_color))
            self._tag.set_property('font', self._font)
            self._tag.set_property('weight',
                                   self._style & STYLE_BOLD and
                                   pango.WEIGHT_BOLD or
                                   pango.WEIGHT_NORMAL)
            self._tag.set_property('underline',
                                   self._style & STYLE_UNDERLINE and
                                   pango.UNDERLINE_SINGLE or
                                   pango.UNDERLINE_NONE)
            self._tag.set_property('style',
                                   self._style & STYLE_ITALIC and
                                   pango.STYLE_ITALIC or
                                   pango.STYLE_NORMAL)
            self._tag.set_property('strikethrough',
                                   self._style & STYLE_STRIKETHROUGH and
                                   True or False)
            self._tags.append(self._tag)
            self._tagChanged = False

    def _OnFocus(self, received):
        self._focus = received
                                   
    def _OnKeyPress(self, widget, event, data = None):
        code = event.keyval
        cb = self._bindings.get(code)
        if cb is not None:
            cb()
	
    def OnKeyDown(self, event):
	pass	
    
